﻿using System;
using System.Collections.Generic;
using System.Linq;

using cit.CopyDetection.DatabaseAccess;
using cit.CopyDetection.DataObject;
using cit.CopyDetection.Preprocessing;

namespace cit.CopyDetection.Model
{
    /// <summary>
    /// Cung cấp các chức năng mô hình hóa tài liệu, đoạn văn bản thành các vector
    /// </summary>
    public class ModelCreator
    {
        private List<Term> _vocabulary;
        private List<double> _globalValues; 
        private ILocalWtFunc _localWtFunc;
        private IGlobalWtFunc _globalWtFunc;

        /// <summary>
        /// Hàm đánh trọng số cục bộ
        /// </summary>
        public ILocalWtFunc LocalWtFunc
        {
            get { return _localWtFunc; }
            set { _localWtFunc = value; }
        }        

        /// <summary>
        /// Hàm đánh trọng số toàn cục
        /// </summary>
        public IGlobalWtFunc GlobalWtFunc
        {
            get { return _globalWtFunc; }
            set { _globalWtFunc = value; }
        }

        /// <summary>
        /// Tập từ vựng cho việc mô hình hoá
        /// </summary>
        public List<Term> Vocabulary
        {
            get { return _vocabulary; }
            set { _vocabulary = value; }
        }

        /// <summary>
        /// Khởi tạo đối tượng mô hình hoá
        /// </summary>
        public ModelCreator()
        {
            _vocabulary = TermDataAccess.GetTerms();
        }

        /// <summary>
        /// Khởi tạo đối tượng mô hình hoá
        /// </summary>
        /// <param name="localWtFunc">Hàm đánh trọng từ số cục bộ</param>
        /// <param name="globalWtFunc">Hàm đánh trọng số toàn cục</param>
        public ModelCreator(ILocalWtFunc localWtFunc, IGlobalWtFunc globalWtFunc)
        {
            _vocabulary = TermDataAccess.GetTerms();
            _localWtFunc = localWtFunc;
            _globalWtFunc = globalWtFunc;
        }

        /// <summary>
        /// Mô hình hóa đoạn văn bản đã đăng ký
        /// </summary>
        /// <param name="paragraph">Đoạn văn bản cần mô hình hóa</param>
        /// <param name="terms">Danh sách các từ trong đoạn văn bản</param>
        /// <returns>Mô hình đoạn văn bản</returns>
        private ParagraphModel ModelRegisteredParagraph(Paragraph paragraph, List<Term> terms)
        {
            int size = _vocabulary.Count;
            ParagraphModel paraModel = new ParagraphModel(paragraph, size);            
            for (int i = 0; i < size; i++)
            {
                paraModel.Vector[i] = _localWtFunc.Apply(_vocabulary[i], terms) * _globalValues[i];
            }
            return paraModel;
        }

        /// <summary>
        /// Mô hình hóa đoạn văn bản kiểm tra
        /// </summary>
        /// <param name="paragraph">Đoạn văn bản cần mô hình hóa</param>
        /// <param name="terms">Danh sách các từ trong đoạn văn bản</param>
        /// <returns>Mô hình đoạn văn bản</returns>
        private ParagraphModel ModelVerifiedParagraph(Paragraph paragraph, List<Term> terms) 
        {
            int size = _vocabulary.Count;
            ParagraphModel paraModel = new ParagraphModel(paragraph, size);
            for (int i = 0; i < size; i++)
            {
                paraModel.Vector[i] = _localWtFunc.Apply(_vocabulary[i], terms);
            }
            return paraModel;
        }

        /// <summary>
        /// Mô hình hóa tài liệu đăng ký
        /// </summary>
        /// <param name="positions">Vị trí các tài liệu trong mô hình</param>
        /// <returns>Tập các vector đoạn văn bản</returns>
        public List<ParagraphModel> ModelRegisteredDocuments(out Dictionary<Document, Position> positions)
        {
            List<Paragraph> paragraphs = new List<Paragraph>(); 
            List<ParagraphModel> paraModels = new List<ParagraphModel>();
            int index = 0, nparagraphs = 0;
                        
            positions = new Dictionary<Document, Position>();
            List<Document> documents = DocumentDataAccess.GetDocuments();
            foreach(Document document in documents)
            {
                paragraphs.AddRange(DocumentDataAccess.GetParagraphs(document));
                nparagraphs = paragraphs.Count;
                positions.Add(document, new Position() { Begin = index, End = nparagraphs - 1 });
                index = nparagraphs;
            }

            if (_globalValues == null)
                _globalValues = _globalWtFunc.ComputeGlobalWeights(_vocabulary, nparagraphs);

            foreach (Paragraph paragraph in paragraphs)
            {
                paraModels.Add(ModelRegisteredParagraph(paragraph, TermDataAccess.GetTerms(paragraph)));
            }

            return paraModels;
        }

        /// <summary>
        /// Mô hình hóa tài liệu kiểm tra
        /// </summary>
        /// <param name="location">Địa chỉ tài liệu</param>
        /// <returns>Tập các vector đoạn văn bản</returns>
        public List<ParagraphModel> ModelVerifiedDocument(string location) 
        {
            TextSegmenter segmenter = new TextSegmenter();
            string[] paragraphs = segmenter.SegmentFileinParagraphs(location);

            int paraNum = 0;
            int size = paragraphs.Length;
            List<ParagraphModel> paraModels = new List<ParagraphModel>(size);
            for (int i = 0; i < size; i++)
            {
                List<Term> terms = segmenter.SegmentTextinTerms(paragraphs[i]);
                if (terms != null)
                {
                    int length = terms.Sum(term => term.GlobalFrequency);
                    paraModels.Add(ModelVerifiedParagraph(new Paragraph(++paraNum, location, length), terms));    
                }
            }
            
            return paraModels;
        }
    }
}
